﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using K9Nano.Dependency;
using K9Nano.Domain;
using K9Nano.MultiTenancy;
using K9Nano.Runtime;
using K9Nano.Share.Exceptions;
using K9Nano.Share.Extensions;
using Microsoft.Extensions.Logging;

namespace K9Nano.Application.MultiTenancy
{
    public class TenantAppService : K9ApplicationService, ITenantAppService, IScopedDependency
    {
        protected IRepository<Tenant, Guid> Repository;

        public TenantAppService(IUnitOfWork uow, IMapper mapper, ISessionContext sessionContext, ILoggerFactory loggerFactory) : base(uow, mapper, sessionContext, loggerFactory)
        {
            Repository = uow.Repository<Tenant, Guid>();
        }

        public async ValueTask<TenantInfo> CreateAsync(TenantCreateInput input, CancellationToken cancellation)
        {
            if (await Repository.AnyAsync(x => x.Name == input.Name, cancellation))
            {
                throw new K9UserFriendlyException($"租户{input.Name}已经存在");
            }

            var tenant = Mapper.Map<Tenant>(input);
            await Repository.InsertAsync(tenant, cancellation);
            return new TenantInfo(tenant.Id, tenant.Name);
        }

        public async ValueTask DeleteAsync(string id, CancellationToken cancellation)
        {
            var gid = Guid.Parse(id);
            var tenant = await Repository.GetAsync(gid, cancellation);
            if (tenant != null)
            {
                await Repository.DeleteAsync(tenant, true, cancellation);
            }
        }

        public async ValueTask UpdateAsync(TenantEditInput input, CancellationToken cancellation)
        {
            var gid = Guid.Parse(input.Id);
            var tenant = await Repository.GetAsync(gid, cancellation);
            if (tenant == null)
            {
                throw new K9UserFriendlyException($"租户{input.Id}不存在");
            }
            await Repository.UpdateAsync(tenant, cancellation);
        }

        public async ValueTask<PagedResultDto<TenantDto>> GetPagedListAsync(TenantPagedInput input, CancellationToken cancellation)
        {
            int count;
            var predicate = input.Predicate();
            if (predicate == null)
            {
                count = await Repository.CountAsync(cancellation);
            }
            else
            {
                count = await Repository.CountAsync(predicate, cancellation);
            }

            if (count <= 0)
            {
                return new PagedResultDto<TenantDto>();
            }
            var list = await Repository.GetPagedListAsync(input, cancellation);
            return new PagedResultDto<TenantDto>(count, Mapper.Map<List<TenantDto>>(list));
        }
    }
}